package v1

import (
	"encoding/json"
	"fmt"
	"goim/server/common/model"
	"goim/server/system/global"
	"goim/server/system/middleware"
	"goim/server/util"
	"net/http"
	"time"

	"github.com/gin-gonic/gin"
	"github.com/gorilla/websocket"
)

type Message struct {
	ApiBaseNoVerify
}

var upgrader = websocket.Upgrader{
	CheckOrigin: func(r *http.Request) bool {
		return true // 允许跨域请求
	},
}

type Msg struct {
	Sender    string `json:"sender"`    //发件人
	Recipient string `json:"recipient"` //收件人
	Content   string `json:"content"`   //消息内容
}

type MsgContentDecode struct {
	From_id uint64
	To_id   uint64
	Content string
	Token   string
	Uid     uint64
}

type HisotryUserMsg struct {
	model.Message
	Place    string
	Bg       string
	Identity uint8
	Nickname string
	Realname string
	Username string
	Phone    string
	Avatar   string
	Sex      uint8
	Age      uint8
}

type Client struct {
	Conn *websocket.Conn
}

var clients = make(map[string]*websocket.Conn)
var MsgM = new(model.MessageModel)

// WebSocket处理消息
func (s Message) NetMsg(c *gin.Context) {

	// 检查WebSocket的升级请求
	if websocket.IsWebSocketUpgrade(c.Request) {

		conn, err := upgrader.Upgrade(c.Writer, c.Request, nil)
		if err != nil {
			fmt.Println("WebSocket协议升级失败")
			return
		}
		defer conn.Close()

		//连接对象Map的Key
		var connKey map[string]string = s.clientInfo(conn, c)
		clients[connKey["conn_key"]] = conn

		//心跳监测
		go s.Heartbeat(conn)
		for {
			mt, message, err := conn.ReadMessage()
			if err != nil {
				global.JLZS_LOG.Info("WebSocket 读取消息失败")
				fmt.Println("WebSocket 读取消息失败")
				fmt.Println(err)
				return
			}

			if len(message) > 0 {
				go s.MsgHandle(mt, message, connKey["conn_key"], conn, c)
			}
		}
	} else {
		c.JSON(http.StatusBadRequest, gin.H{"error": "Non-websocket upgrade request"})
	}
}

// 信息处理
func (s Message) MsgHandle(mt int, msg []byte, connKey string, conn *websocket.Conn, c *gin.Context) {
	fmt.Printf("前端: %s\n", msg)

	var msgH MsgContentDecode
	json.Unmarshal(msg, &msgH)
	var addDbMap = make(map[string]string)
	addDbMap["from_id"] = util.Uint64ToStr(msgH.From_id)
	addDbMap["to_id"] = util.Uint64ToStr(msgH.To_id)
	addDbMap["content"] = msgH.Content
	MsgM.AddMsg(addDbMap)

	//临时注释，勿删
	//reMsgList, _, _ := MsgM.ListData(0, nil)
	//reUserMsg, _ := s.historyHandle(reMsgList, msgH.Uid)

	for _, v := range clients {
		v.WriteMessage(mt, []byte(msgH.Content))
	}
	MsgM = nil
}

func (s Message) Heartbeat(ws *websocket.Conn) {
	pingTicker := time.NewTicker(time.Second * 30)   // 每26秒发送一次ping
	pongTicker := time.NewTicker(time.Second * 3600) // 每30秒没有收到pong就关闭连接

	defer func() {
		pingTicker.Stop()
		pongTicker.Stop()
		ws.Close()
	}()

	for {
		select {
		case <-pingTicker.C:
			ws.SetWriteDeadline(time.Now().Add(time.Second))
			if err := ws.WriteMessage(websocket.PingMessage, []byte{}); err != nil {
				return
			}
		case <-pongTicker.C:
			return
		}
	}
}

// 获取客户端信息
func (s Message) clientInfo(ws *websocket.Conn, c *gin.Context) map[string]string {

	var token string = c.Request.URL.Query().Get("token")
	var reVal = make(map[string]string)
	if token != "" {
		reMidd, _ := middleware.ParseT(token)
		fmt.Println(token)
		reVal["uid"] = reMidd.Uid
		reVal["Mobile"] = reMidd.Mobile
		reVal["conn_key"] = util.Md5(reMidd.Mobile)
	}
	return reVal
}

// 历史信息结构展示处理
func (s Message) historyHandle(msgList []model.Message, uid uint64) ([]HisotryUserMsg, error) {

	userM := new(model.UserModel)
	uInfo, _, _ := userM.Detail(uid, nil)
	var msgLL int = len(msgList)
	var fromId []uint64
	for i := 0; i < msgLL; i++ {
		if msgList[i].From_id != uid {
			fromId = append(fromId, msgList[i].From_id)
		}
	}
	if len(fromId) > 0 {
		reUser, err := userM.UserList(fromId, "")
		if err != nil {
			return nil, err
		}
		var reUserLen int = len(reUser)
		if reUserLen > 0 {

			var hum []HisotryUserMsg
			var tmpHum HisotryUserMsg
			for iml := 0; iml < msgLL; iml++ {

				tmpHum.Mid = msgList[iml].Mid
				tmpHum.From_id = msgList[iml].From_id
				tmpHum.To_id = msgList[iml].To_id
				tmpHum.Content = msgList[iml].Content
				tmpHum.Create_time = msgList[iml].Create_time
				if tmpHum.From_id == uid {
					tmpHum.Place = "r"
					tmpHum.Bg = "#07C160"
					tmpHum.Identity = 1
					tmpHum.Nickname = uInfo.Nickname
					tmpHum.Realname = uInfo.Realname
					tmpHum.Username = uInfo.Username
					tmpHum.Phone = uInfo.Phone
					tmpHum.Avatar = uInfo.Avatar
					tmpHum.Sex = uInfo.Sex
					tmpHum.Age = uInfo.Age

				} else {
					tmpHum.Place = "l"
					tmpHum.Bg = "#FFFFFF"
					tmpHum.Identity = 0
					for irul := 0; irul < reUserLen; irul++ {
						tmpHum.Nickname = reUser[irul].Nickname
						tmpHum.Realname = reUser[irul].Realname
						tmpHum.Username = reUser[irul].Username
						tmpHum.Phone = reUser[irul].Phone
						tmpHum.Avatar = reUser[irul].Avatar
						tmpHum.Sex = reUser[irul].Sex
						tmpHum.Age = reUser[irul].Age
					}
				}
				hum = append(hum, tmpHum)
			}
			return hum, nil
		}
	}
	return nil, nil
}
